﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using eLuk.CommandEngine;
using Windows.Foundation;

namespace eLuk.CommandEngine
{
	public class IMAPCommandEngine : ClientCommandEngine
	{
		public IMAPCommandEngine()
		{
			//this.ChannelLinkLoadCompleted += IMAPCommandEngine_ChannelLinkLoadCompleted;
			//this.ChannelLinkWriteCompleted += IMAPCommandEngine_ChannelLinkWriteCompleted;
			//this.CommandFormatter = new CommandFormatter();
		}

		public Channel Channel { get; set; }
		
		public override string Execute( IMAPCommand command, params object[] CommandParams )
		{
			string response = "";

			string result = "";
			try
			{
				byte[] bytes = command.Prepare( CommandParams );
				this.Channel.Writer.WriteBytes( bytes );

				//changed in flight
				this.Channel.Writer.StoreAsync();

				if ( command.Name == "UID FETCH" )
					Misc.Delay( 3000 );
				else
					Misc.Delay( 1000 );

				this.Channel.Reader.LoadAsync( Channel.MaxBufferSize );

				if ( command.Name == "UID FETCH" )
					Misc.Delay( 3000 );
				else
					Misc.Delay( 1000 );


				string latestRead = "";

				do
				{
					latestRead = this.Channel.Reader.ReadLine().GetAwaiter().GetResult();


					if ( latestRead == null )
						latestRead = "";

					if ( latestRead.StartsWith( command.SuccessResponseStart ) )
					{
						response = result;
					}
					else if ( latestRead.StartsWith( command.SuccessResponseStart ) )
					{
					}
					else if ( latestRead.StartsWith( command.CommonFailureStart[ 0 ] ) || latestRead.StartsWith( command.CommonFailureStart[ 1 ] )
						|| latestRead.StartsWith( command.CommonFailureStart[ 2 ] ) )
					{

					}
					else
					{
						result += latestRead;
					}
				}
				while ( this.Channel.Reader.UnconsumedBufferLength != 0 );
			}
			catch ( Exception ex )
			{
				response = ex.Message;
			}

			//if ( response.Trim() == "" && result.EndsWith( "OK Success\r\n" ) )
			//	response = result;

			if ( response.Trim() == "" )
				return result;
			return response;
		}

		public async override Task<string> ExecuteAsync( IMAPCommand command, params object[] CommandParams )
		{
			string response = "";
			string lastLine = "";
			string latestRead = "";

			try
			{
				byte[] bytes = command.Prepare( CommandParams );

//#if TEAVCH_DEBUG
				//await Misc.WriteFile( command.Command );
//#endif

				if ( command.Command.Contains( "FETCH 607" ) )
				{
					;
				}
				this.Channel.Writer.WriteBytes( bytes );
				await this.Channel.Writer.StoreAsync();
				//Misc.Delay( 1000 );
				IAsyncOperation<uint> task = this.Channel.Reader.LoadAsync( Channel.MaxReadBufferSize );
				task.AsTask().Wait();
				task.GetResults();


				do
				{
					latestRead = this.Channel.Reader.ReadString( this.Channel.Reader.UnconsumedBufferLength );
					if ( latestRead == null )
						latestRead = "";
					if ( latestRead.Trim() != "" )
					{
						response += latestRead;
					}
					lastLine = response.LastLine();
					if ( lastLine.StartsWith( command.SuccessResponseStart ) )
					{
						int iIndex = response.LastIndexOf( command.SuccessResponseStart );
						iIndex = iIndex < 0 ? 0 : iIndex;
						response = response.Substring( 0, iIndex );
//#if TEAVCH_DEBUG
						//await Misc.WriteFile( response );
//#endif

						return response;
					}
					else if ( lastLine.StartsWith( command.FailureResponseStart ) )
					{
						response = "";
						return response;
					}
					else if ( lastLine.StartsWith( command.ErrorResponseStart ) )
					{
						response = "";
						return response;
					}
					task = this.Channel.Reader.LoadAsync( Channel.MaxReadBufferSize );
					task.AsTask().Wait();
					task.GetResults();
				}
				while ( true );
			}
			catch ( Exception ex )
			{
				response = ex.Message;
			}

			return response;
		}

		private async Task<string> ChannelLinkWriteCompleted( IMAPCommand command )
		{

			//ChannelLinkLoadCompletedEventArgs loadEvent = new ChannelLinkLoadCompletedEventArgs();
			//loadEvent.Command = e.Command;
			string result = await this.ChannelLinkLoadCompleted( command );
			return result;
		}

		private async Task<string> ChannelLinkLoadCompleted( IMAPCommand command )
		{
			string result = "";
			string latestRead = "";

			do
			{
				latestRead = await this.Channel.Reader.ReadLine();

				if ( latestRead == null )
					latestRead = "";

				if ( latestRead.StartsWith( command.SuccessResponseStart ) )
				{
				}
				else if ( latestRead.StartsWith( command.SuccessResponseStart ) )
				{
				}
				else if ( latestRead.StartsWith( command.CommonFailureStart[ 0 ] ) || latestRead.StartsWith( command.CommonFailureStart[ 1 ] )
					|| latestRead.StartsWith( command.CommonFailureStart[ 2 ] ) )
				{
				}
				else
				{
					result += latestRead;
				}
			}
			while ( this.Channel.Reader.UnconsumedBufferLength != 0 );
			return result;
		}

		public async override Task InitializeAsync( EmailServer _server )
		{
			this.Channel = new Channel( _server );
			this.Channel.IsConnected = await this.Channel.SetSocketAsync();
		}

	}

	public abstract class ClientCommandEngine
	{
		public abstract string Execute( IMAPCommand command, params object[] CommandParams );
		public abstract Task<string> ExecuteAsync( IMAPCommand command, params object[] CommandParams );
		public abstract Task InitializeAsync( EmailServer _server );
	}
}
